import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { showToast, showDialog } from 'vant'
import NProgress from './nprogress'
import { getEnvConfig } from './env'
import TokenService from './tokenService'
import { useUserStore } from '../stores/user'
import { useRouter } from 'vue-router'

const { BASE_API } = getEnvConfig()

// 创建 axios 实例
const service: AxiosInstance = axios.create({
  baseURL: getEnvConfig().BASE_API + '/api',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
  },
})

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    NProgress.start()
    // 使用 TokenService 获取 token
    const token = TokenService.getToken()
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => {
    NProgress.done()
    return Promise.reject(error)
  },
)

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    NProgress.done()
    const res = response.data
    if (res.code !== 0) {
      showToast({
        message: res.message || '请求失败',
        type: 'fail',
      })
      // 处理 401 未授权
      if (res.code === 401) {
        handleUnauthorized()
      }
      return Promise.reject(new Error(res.message || '请求失败'))
    }
    return res
  },
  (error) => {
    NProgress.done()
    // 处理 401 未授权
    if (error.response?.status === 401) {
      handleUnauthorized()
    } else {
      showToast({
        message: error.message || '网络错误',
        type: 'fail',
      })
    }
    return Promise.reject(error)
  },
)

// 统一处理未授权情况
const handleUnauthorized = () => {
  const { logout } = useUserStore()
  showDialog({
    title: '提示',
    message: '登录已过期，请重新登录',
    confirmButtonText: '重新登录',
    showCancelButton: false,
  }).then(() => {
    logout()
    const router = useRouter()
    router.replace({
      path: '/login',
      query: { redirect: router.currentRoute.value.fullPath },
    })
  })
}

// Fetch 封装
export const fetchRequest = async (url: string, options: RequestInit = {}) => {
  try {
    NProgress.start()
    const token = TokenService.getToken()
    const defaultOptions: RequestInit = {
      headers: {
        'Content-Type': 'application/json',
        ...(token ? { Authorization: `Bearer ${token}` } : {}),
      },
      credentials: 'include',
    }

    const response = await fetch(`${BASE_API}/api${url}`, {
      ...defaultOptions,
      ...options,
      headers: {
        ...defaultOptions.headers,
        ...options.headers,
      },
    })

    NProgress.done()

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const data = await response.json()

    if (data.code !== 0) {
      showToast({
        message: data.message || '请求失败',
        type: 'fail',
      })
      if (data.code === 401) {
        showDialog({
          title: '提示',
          message: '登录已过期，请重新登录',
        }).then(() => {
          localStorage.removeItem('token')
          window.location.href = '/login'
        })
      }
      throw new Error(data.message || '请求失败')
    }

    return data
  } catch (error) {
    NProgress.done()
    showToast({
      message: error.message || '网络错误',
      type: 'fail',
    })
    throw error
  }
}

// 导出请求方法
export const request = {
  get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return service.get(url, config)
  },

  post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return service.post(url, data, config)
  },

  put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return service.put(url, data, config)
  },

  delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return service.delete(url, config)
  },

  // Fetch 方法
  fetch: {
    get: (url: string, options?: RequestInit) => fetchRequest(url, { method: 'GET', ...options }),

    post: (url: string, data?: any, options?: RequestInit) =>
      fetchRequest(url, {
        method: 'POST',
        body: JSON.stringify(data),
        ...options,
      }),

    put: (url: string, data?: any, options?: RequestInit) =>
      fetchRequest(url, {
        method: 'PUT',
        body: JSON.stringify(data),
        ...options,
      }),

    delete: (url: string, options?: RequestInit) =>
      fetchRequest(url, { method: 'DELETE', ...options }),
  },
}

export default request
